import { forEachValue } from "./utils";
import withMutation from "./with-mutation";

// 获取实时的state的值，因为会有一个更新state的函数会修改state因此getter也应该同步修改
function getNestedState(store, path) {
  return path.reduce((acc, cur) => acc[cur], store.state);
}

export default function installModule(
  store,
  state,
  getters,
  mutations,
  actions,
  path,
  module
) {
  if (path.length !== 0) {
    withMutation.call(
      store,
      () => (state[path[path.length - 1]] = module.state)
    );
  }

  // getter应该是响应式的数据，用函数返回值来实现
  forEachValue(module._raw.getters, (getter, key) => {
    getters[path[path.length - 1]] =
      getters[path[path.length - 1]] ?? Object.create(null);
    Object.defineProperty(
      path.length !== 0 ? getters[path[path.length - 1]] : getters,
      key,
      {
        get: () => getter(getNestedState(store, path)),
        enumerable: true,
      }
    );
  });

  // mutations
  forEachValue(module._raw.mutations, (mutation, key) => {
    const namespacedKey =
      module.namespacedPath + `${module.namespacedPath ? "/" : ""}` + key;
    !mutations[namespacedKey] && (mutations[namespacedKey] = []);
    mutations[namespacedKey].push((payload) => {
      mutation(
        path.length !== 0
          ? path.reduce((acc, cur) => acc[cur], store.state)
          : store.state,
        payload
      );
    });
  });

  // actions
  forEachValue(module._raw.actions, (action, key) => {
    const namespacedKey =
      module.namespacedPath + `${module.namespacedPath ? "/" : ""}` + key;
    !actions[namespacedKey] && (actions[namespacedKey] = []);
    actions[namespacedKey].push((payload) => action(store, payload));
  });

  // 递归遍历
  forEachValue(module._children, (child, key) => {
    installModule(
      store,
      path.length === 0 ? state : state[path[path.length - 1]],
      path.length === 0 ? getters : getters[path[path.length - 1]],
      mutations,
      actions,
      path.concat([key]),
      child
    );
  });
}
